/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.gui.server;

import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.server.rpc.*;
import nfse.gui.config.*;

import nfse.NetFSE;
import nfse.NetFSEUtil;
import nfse.gui.client.NetFSEClient;
import nfse.gui.query.*;
import java.io.*;
import java.sql.*;
import java.util.*;

import javax.net.SocketFactory;
import java.net.Socket;

import nfse.NetFSERecord;
import nfse.DataServer;

public class ConfigServiceImpl extends RemoteServiceServlet implements ConfigService {

    private static Connection connectionResult = null;

    private static Connection connectionMetadata = null;

    private String[] predicates = { "=", "~", "&lt;", "&gt;", "&lt;=", "&gt;=" };

    public ConfigServiceImpl() {
        super();

        try {

        } catch (Exception e) {
            e.printStackTrace();
        }

        if (NetFSE.TYPE_CLASS_NAMES == null) {
            try {
                NetFSE.configure(NetFSE.CONFIG_FILE);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void deleteSyslogConfig(SyslogConfig config) {
        try {
            String sql = "delete from syslog_agent_conf where sensor=" + config.sensor + "";
            Statement s = createMetadataStatement();
            // System.out.println(sql);
            s.execute(sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void deleteNetFlowConfig(NetFlowConfig config) {
        try {
            String sql = "delete from netflow_agent_conf where sensor=" + config.sensor + "";
            Statement s = createMetadataStatement();
            s.execute(sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void deleteSensor(int sensorID) {
        try {
            String sql = "update sensors set tool_id = -1 where id=" + sensorID + "";
            Statement s = createMetadataStatement();
            s.execute(sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String syslogAndNetFlowControl(int sensorID, int opType) {
        String message = "";
        try {
            // System.out.println("Sensor: " + sensorID + ", Op: " + opType);
            String userName = getUserName();

            boolean admin = isAdmin(userName);
            if (!admin)
                return "You must be an admin to execute this function.";

            SocketFactory sf = SocketFactory.getDefault();
            Socket socket = sf.createSocket("localhost", NetFSE.CONTROL_SERVER_PORT);
            DataOutputStream socketOut = new DataOutputStream(socket.getOutputStream());
            DataInputStream socketIn = new DataInputStream(socket.getInputStream());

            socketOut.writeInt(sensorID);
            socketOut.writeInt(opType);

            int reply = socketIn.readInt();

            socketIn.close();
            socketOut.close();
            socket.close();

            message = "Operation complete.";
        } catch (Exception e) {
            e.printStackTrace();
            message = e.getMessage();
        }
        System.out.println(message);
        return message;
    }

    public SensorInfo[] getSensorInfo() {
        SensorInfo[] results = null;
        try {
            Vector temp = new Vector();
            String sql = "select a.id as sensor_id, a.name as sensor_name, b.name as type_name, b.id as type_id from sensors a, tools b  where a.tool_id=b.id and tool_id != -1";
            Statement s = createMetadataStatement();
            ResultSet rs = s.executeQuery(sql);
            while (rs.next()) {
                SensorInfo info = new SensorInfo();
                info.id = rs.getInt("sensor_id");
                info.sensorName = rs.getString("sensor_name");
                info.typeName = rs.getString("type_name");
                NetFSERecord rec = NetFSE.getTypeClass(rs.getInt("type_id"));
                info.isSyslog = rec.isSyslog();
                temp.addElement(info);
            }
            rs.close();
            s.close();
            results = new SensorInfo[temp.size()];
            for (int i = 0; i < results.length; i++) {
                results[i] = (SensorInfo) temp.elementAt(i);
            }
            return results;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return results;
    }
    
    public SoleraConfig[] getSoleraConfigs() {
        SoleraConfig[] results = null;
        try {
            Vector temp = new Vector();
            String sql = "select * from sensors a, solera_sensors b  where a.id=b.sensor_id and a.id != -1";
            Statement s = createMetadataStatement();
            ResultSet rs = s.executeQuery(sql);
            while (rs.next()) {
                SoleraConfig info = new SoleraConfig();
                info.sensorID = rs.getInt("sensor_id");
                info.name = rs.getString("name");
                info.ip = rs.getString("ip");
                temp.addElement(info);
            }
            rs.close();
            s.close();
            results = new SoleraConfig[temp.size()];
            for (int i = 0; i < results.length; i++) {
                results[i] = (SoleraConfig) temp.elementAt(i);
            }
            return results;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new SoleraConfig[0];
    }

    public DailyRecordCountInfo getDailyRecordCounts(int numDays) {
        DailyRecordCountInfo result = null;
        try {
            Vector temp = new Vector();
            String sql = "select * from Daily_Record_Counts where Entry_Date > date(now()) - interval '" + numDays
                    + " days'";
            Statement s = createMetadataStatement();
            ResultSet rs = s.executeQuery(sql);
            long secondsNotCollecting = 0;
            long recordsDropped = 0;
            long recordsProcessed = 0;
            while (rs.next()) {
                DailyRecordCount drc = new DailyRecordCount();
                drc.date = rs.getString("Entry_Date");
                drc.recordCount = rs.getLong("records_processed");
                recordsProcessed += drc.recordCount;
                drc.exceededCount = rs.getLong("Records_Over");
                recordsDropped += drc.exceededCount;
                Timestamp ts = rs.getTimestamp("Threshold_TS");
                if (ts == null)
                    drc.exceededTS = "-";
                else {
                    drc.exceededTS = ts.toString();
                    GregorianCalendar cal = new GregorianCalendar();
                    cal.setTimeInMillis(ts.getTime());
                    cal.set(Calendar.HOUR_OF_DAY, 0);
                    cal.set(Calendar.MINUTE, 0);
                    cal.set(Calendar.SECOND, 0);
                    cal.set(Calendar.MILLISECOND, 0);
                    cal.add(Calendar.DAY_OF_MONTH, 1);

                    long ts2 = cal.getTimeInMillis();
                    int sec = (int) ((ts2 - ts.getTime()) / (long) 1000);
                    secondsNotCollecting += sec;

                }

                temp.addElement(drc);
            }
            rs.close();

            int hours = (int) (secondsNotCollecting / 3600);
            int min = (int) ((secondsNotCollecting - hours * 3600) / 60);
            if (min < 0)
                min = 0;

            result = new DailyRecordCountInfo();
            result.recordsDropped = recordsDropped;
            result.totalRecords = recordsProcessed;
            result.numDays = numDays;
            result.recordThreshold = DataServer.RECORD_THRESHOLD;
            result.timeNotCollecting = hours + " ";
            if (hours != 1)
                result.timeNotCollecting += "hrs, ";
            else
                result.timeNotCollecting += "hr, ";
            result.timeNotCollecting += min + " ";
            if (hours != 1)
                result.timeNotCollecting += "mins";
            else
                result.timeNotCollecting += "min";

            s.close();

            result.dailyRecordCounts = new DailyRecordCount[temp.size()];
            for (int i = 0; i < result.dailyRecordCounts.length; i++) {
                result.dailyRecordCounts[i] = (DailyRecordCount) temp.elementAt(i);
            }

            // return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public SyslogConfig[] getSyslogConfigs() {
        SyslogConfig[] results = null;
        try {
            Vector temp = new Vector();
            String sql = "select * from syslog_agent_conf a, sensors b where a.sensor=b.id ";
            Statement s = createMetadataStatement();
            ResultSet rs = s.executeQuery(sql);
            while (rs.next()) {
                int sensor = rs.getInt("sensor");
                String sensorName = rs.getString("name");
                String ip = rs.getString("ip");
                if (ip == null)
                    ip = "";

                String filePath = rs.getString("file_path");
                String keyword = rs.getString("keyword");
                SyslogConfig st = new SyslogConfig();
                st.filePath = filePath;
                st.ip = ip;
                st.keyword = keyword;
                st.sensor = sensor;
                st.sensorName = sensorName;
                temp.addElement(st);
            }
            rs.close();
            s.close();
            results = new SyslogConfig[temp.size()];
            for (int i = 0; i < results.length; i++) {
                results[i] = (SyslogConfig) temp.elementAt(i);
            }
            return results;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return results;
    }

    public NetFlowConfig[] getNetFlowConfigs() {
        NetFlowConfig[] results = null;
        try {
            Vector temp = new Vector();
            String sql = "select * from netflow_agent_conf a, sensors b where a.sensor=b.id ";
            Statement s = createMetadataStatement();
            ResultSet rs = s.executeQuery(sql);
            while (rs.next()) {
                int sensor = rs.getInt("sensor");
                int port = rs.getInt("port");
                String sensorName = rs.getString("name");
                NetFlowConfig st = new NetFlowConfig();
                st.sensor = sensor;
                st.sensorName = sensorName;
                st.port = port;
                temp.addElement(st);
            }
            rs.close();
            s.close();
            results = new NetFlowConfig[temp.size()];
            for (int i = 0; i < results.length; i++) {
                results[i] = (NetFlowConfig) temp.elementAt(i);
            }
            return results;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return results;
    }

    public String addSensor(SensorInfo info) {
        try {
            Statement statement = createMetadataStatement();

            String sql = "select * from Sensors where Name='" + info.sensorName + "'";
            ResultSet rs = statement.executeQuery(sql);
            if (rs.next()) {
                int typeID = rs.getInt("Tool_ID");
                rs.close();
                statement.close();
                if (typeID == -1)
                    return "Request failed: a sensor named '" + info.sensorName
                            + "' previously existed. Chose another name.";
                else
                    return "Request failed: a sensor named '" + info.sensorName
                            + "' already existed. Chose another name.";
            }
            rs.close();

            sql = "insert into Sensors values (nextval('sensor_id_seq')," + info.type + ",'" + info.sensorName + "')";
            statement.execute(sql);

            statement.close();
        } catch (Exception E) {
            E.printStackTrace();
            return "Request failed: " + E.getMessage();
        }
        return "Add Sensor request completed.";
    }

    public String addNetFlowConfig(NetFlowConfig config) {
        try {
            Statement statement = createMetadataStatement();

            String sql = "select * from netflow_agent_conf where sensor=" + config.sensor + "";
            ResultSet rs = statement.executeQuery(sql);
            if (rs.next()) {
                rs.close();
                statement.close();
                return "Request failed: a configuration for the sensor '" + NetFSE.getSensorInfo(config.sensor).getName()
                        + "' already exists.";
            }
            rs.close();

            sql = "select * from netflow_agent_conf where port=" + config.port + "";
            rs = statement.executeQuery(sql);
            if (rs.next()) {
                rs.close();
                statement.close();
                return "Request failed: an existing configuration is already using port " + config.port + ".";
            }
            rs.close();

            sql = "insert into netflow_agent_conf values (" + config.sensor + "," + config.port + ")";
            statement.execute(sql);

            statement.close();
        } catch (Exception E) {
            E.printStackTrace();
            return "Request failed: " + E.getMessage();
        }
        return "Add NetFlow agent configuration request completed.";
    }

    public String addSyslogConfig(SyslogConfig config) {
        try {
            Statement statement = createMetadataStatement();

            String sql = "select * from syslog_agent_conf where sensor=" + config.sensor + "";
            ResultSet rs = statement.executeQuery(sql);
            if (rs.next()) {
                rs.close();
                statement.close();
                return "Request failed: a configuration already exists for sensor '"
                        + NetFSE.getSensorInfo(config.sensor).getName() + "'";

            }
            rs.close();

            File f = new File(config.filePath);
            if (!f.exists()) {
                statement.close();
                return "Add Syslog Configuration request failed because the specified file does not exist.";
            }

            String ipVal = "null";
            if (config.ip.length() > 0) {
                ipVal = "'" + config.ip + "'";
            }

            sql = "insert into syslog_agent_conf values (" + config.sensor + ",'" + config.filePath + "','"
                    + config.keyword + "'," + ipVal + ")";
            statement.execute(sql);

            statement.close();
        } catch (Exception E) {
            E.printStackTrace();
            return "Request failed: " + E.getMessage();
        }
        return "Add Syslog Configuration request completed.";
    }

    public String editSyslogConfig(SyslogConfig config) {
        try {
            deleteSyslogConfig(config);
            addSyslogConfig(config);
        } catch (Exception E) {
            E.printStackTrace();
            return "Request failed: " + E.getMessage();
        }
        return "Edit syslog configuration request completed.";
    }

    public String editNetFlowConfig(NetFlowConfig config) {
        try {
            deleteNetFlowConfig(config);
            addNetFlowConfig(config);
        } catch (Exception E) {
            E.printStackTrace();
            return "Request failed: " + E.getMessage();
        }
        return "Edit NetFlow configuration request completed.";
    }

    public String addCriticalServer(CriticalServerEntry server) {
        try {
            Statement statement = createMetadataStatement();

            String sql = "select * from Critical_Servers where Server_IP='" + server.ip + "'";
            ResultSet rs = statement.executeQuery(sql);
            if (rs.next()) {
                rs.close();
                statement.close();
                return "Request failed: a critical server entry already exists for " + server.ip + "";
            }
            rs.close();

            int asSrc = 0;
            if (server.asSrc)
                asSrc = 1;
            int asDst = 0;
            if (server.asDst)
                asDst = 1;

            sql = "insert into Critical_Servers values ('" + server.ip + "','', " + asSrc + "," + asDst + ", '"
                    + NetFSEUtil.convertToHex(server.note) + "')";
            statement.execute(sql);

            statement.close();
        } catch (Exception E) {
            E.printStackTrace();
            return "Request failed: " + E.getMessage();
        }
        return "Add Critical Server request completed.";
    }

    public String addUser(UserInfo userInfo) {
        try {

            String userName = getUserName();

            boolean admin = isAdmin(userName);
            if (!admin)
                return "You must be an admin to execute this function.";

            Statement statement = createMetadataStatement();

            int adminVal = 0;
            if (userInfo.admin)
                adminVal = 1;
            String sql = "insert into Users values (nextval('user_id_seq'),'" + userInfo.userName + "','"
                    + userInfo.password + "','" + userInfo.realName + "'," + adminVal + ",0)";
            statement.execute(sql);
            statement.close();
            return "Added user '" + userInfo.userName + "'.";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "Add user failed.";
    }

    private String convertFromHex(String line) {
        byte[] bytes = new byte[line.length() / 2];
        for (int i = 0; i < bytes.length; i++)
            bytes[i] = (byte) Integer.parseInt(line.substring(i * 2, i * 2 + 2), 16);
        return new String(bytes);
    }

    private Statement createResultStatement() throws Exception {
        Statement s = null;
        try {
            s = connectionResult.createStatement();
        } catch (Exception e) {
            Class.forName("org.postgresql.Driver");
            String url = "jdbc:postgresql://localhost/" + NetFSE.RESULT_DB_DATABASE;
            Properties props = new Properties();
            props.setProperty("user", NetFSE.RESULT_DB_USER);
            props.setProperty("password", NetFSE.RESULT_DB_PASSWORD);
            props.setProperty("client_encoding", "UTF8");

            connectionResult = DriverManager.getConnection(url, props);

            s = connectionResult.createStatement();
        }
        return s;
    }

    private Statement createMetadataStatement() throws Exception {
        Statement s = null;
        try {
            s = connectionMetadata.createStatement();
        } catch (Exception e) {
            Class.forName("org.postgresql.Driver");
            String url = "jdbc:postgresql://" + NetFSE.METADATA_HOST + "/" + NetFSE.METADATA_DATABASE;
            Properties props = new Properties();
            props.setProperty("user", NetFSE.METADATA_USER);
            props.setProperty("password", NetFSE.METADATA_PASSWORD);
            props.setProperty("client_encoding", "UTF8");

            connectionMetadata = DriverManager.getConnection(url, props);

            s = connectionMetadata.createStatement();
        }
        return s;
    }

    public CriticalServerEntry[] getCriticalServers() {
        try {
            Vector temp = new Vector();

            Statement statement = createMetadataStatement();
            ResultSet rs = statement.executeQuery("select * from Critical_Servers");
            while (rs.next()) {
                CriticalServerEntry cse = new CriticalServerEntry();
                cse.ip = rs.getString("Server_IP");
                int asSrc = rs.getInt("As_Src");
                if (asSrc == 1) {
                    cse.asSrc = true;
                } else {
                    cse.asSrc = false;
                }
                int asDst = rs.getInt("As_Dst");
                if (asDst == 1) {
                    cse.asDst = true;
                } else {
                    cse.asDst = false;
                }
                String note = rs.getString("Note");
                if (note == null)
                    note = "";
                cse.note = NetFSEUtil.convertFromHex(note);
                temp.addElement(cse);
            }
            rs.close();
            statement.close();

            CriticalServerEntry[] results = new CriticalServerEntry[temp.size()];
            for (int i = 0; i < results.length; i++) {
                results[i] = (CriticalServerEntry) temp.elementAt(i);
            }
            return results;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new CriticalServerEntry[0];
    }

    public EmailReportConfigs getEmailReportConfigs() {
        try {

            Statement statement = createMetadataStatement();
            EmailReportConfigs temp = new EmailReportConfigs();

            String sql = "select * from Email_Report_Config ";
            ResultSet rs = statement.executeQuery(sql);
            if (rs.next()) {
                temp.address = rs.getString("Email_Address");
                temp.frequency = rs.getInt("Frequency");
                temp.server = rs.getString("SMTP_Server");
                if (temp.server == null)
                    temp.server = "";
            } else {

            }
            rs.close();

            statement.close();
            return temp;
        } catch (Exception E) {
            E.printStackTrace();
        }
        return null;
    }

    private String getError(int reply) {
        String temp = "Unknown error";
        switch (reply) {
        case -1:
            temp = "Query parse error";
            break;
        case -2:
            temp = "MetaDatabase connection error";
            break;
        case -3:
            temp = "User authentication error";
            break;
        case -4:
            temp = "Invalid query error";
            break;
        case -5:
            temp = "Empty query error";
            break;

        }
        return temp;
    }

    public QueryInfo getQueryInfo(String queryID) {
        try {
            QueryInfo info = new QueryInfo();
            Statement statement = null;
            try {
                statement = connectionResult.createStatement();
            } catch (Exception e) {
                e.printStackTrace();
                Class.forName("com.mysql.jdbc.Driver").newInstance();
                connectionResult = DriverManager.getConnection("jdbc:mysql://" + NetFSE.RESULT_DB_HOST + "/"
                        + NetFSE.RESULT_DB_DATABASE, NetFSE.RESULT_DB_USER, NetFSE.RESULT_DB_PASSWORD);
                statement = connectionResult.createStatement();
            }

            String sql = "select Note from Queries where Query_ID='" + queryID + "'";
            ResultSet rs = statement.executeQuery(sql);
            if (rs.next()) {
                info.note = ServerUtil.convertFromHex(rs.getString("Note"));
                if (info.note == null)
                    info.note = "";
            }
            rs.close();

            Vector types = new Vector();
            sql = "select * from Query_Types where Query_ID='" + queryID + "'";
            rs = statement.executeQuery(sql);
            while (rs.next()) {
                types.addElement(new Integer(rs.getInt("type_id")));
            }
            rs.close();

            info.types = new int[types.size()];
            for (int i = 0; i < info.types.length; i++)
                info.types[i] = ((Integer) types.elementAt(i));

            statement.close();
            return info;
            // c.close();
        } catch (Exception E) {
            E.printStackTrace();
        }
        return null;
    }

    public TypeInfo getTypeInfo() {
        TypeInfo typeInfo = new TypeInfo();
        typeInfo.types = NetFSE.getTypes();
        typeInfo.typeNames = new String[typeInfo.types.length];
        typeInfo.schemas = new String[typeInfo.types.length];
        for (int i = 0; i < typeInfo.types.length; i++) {
            typeInfo.typeNames[i] = NetFSE.getTypeClass(typeInfo.types[i]).getDisplayTypeName();
            typeInfo.schemas[i] = NetFSE.getSchema(typeInfo.types[i]);
        }
        return typeInfo;
    }

    public UserInfo getUserInfo() {
        UserInfo info = null;
        try {

            Statement statement = createMetadataStatement();

            String userName = getUserName();

            String sql = "select * from Users where User_Name='" + userName + "'";
            ResultSet rs = statement.executeQuery(sql);
            if (rs.next()) {
                info = new UserInfo();
                info.userID = rs.getInt("ID");
                info.userName = rs.getString("User_Name");
                info.realName = rs.getString("Real_Name");
                int admin = rs.getInt("Admin");
                if (admin != 0)
                    info.admin = true;
                else
                    info.admin = false;
            } else {
                info = new UserInfo();
                info.admin = true;
                info.userName = "";
            }
            rs.close();

            statement.close();

        } catch (Exception E) {
            E.printStackTrace();
        }
        return info;
    }

    public String getUserName() {
        String userName = this.getThreadLocalRequest().getRemoteUser();
        if (userName == null || userName.length() == 0)
            userName = "";
        return userName;
    }

    public UserInfo[] getUsers() {
        try {
            Statement statement = createMetadataStatement();
            boolean admin = false;
            String userName = getUserName();
            Vector temp = new Vector();
            ResultSet rs = statement.executeQuery("select * from Users ");
            while (rs.next()) {
                UserInfo user = new UserInfo();
                user.userName = rs.getString("User_Name");
                user.realName = rs.getString("Real_Name");
                if (rs.getInt("Admin") != 0) {
                    user.admin = true;
                } else
                    user.admin = false;
                temp.addElement(user);
            }
            rs.close();
            statement.close();

            UserInfo[] users = new UserInfo[temp.size()];
            for (int i = 0; i < users.length; i++) {
                users[i] = (UserInfo) temp.elementAt(i);
            }

            return users;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean isAdmin(String user) {
        try {
            if (user.equals(""))
                return true;

            Statement statement = createMetadataStatement();
            boolean admin = false;
            String userName = getUserName();

            ResultSet rs = statement.executeQuery("select * from Users where User_Name='" + userName + "'");
            if (rs.next()) {
                if (rs.getInt("Admin") != 0) {
                    admin = true;
                }
            }
            rs.close();
            statement.close();
            return admin;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public String removeCriticalServer(String ip) {
        try {
            Statement statement = createMetadataStatement();
            String sql = "select * from Critical_Servers where Server_IP='" + ip + "'";
            ResultSet rs = statement.executeQuery(sql);
            if (!rs.next()) {
                rs.close();
                statement.close();
                return "Request failed: no such entry in critical server list ('" + ip + "')";
            }
            rs.close();

            sql = "delete from Critical_Servers where Server_IP='" + ip + "'";
            statement.execute(sql);

            statement.close();
        } catch (Exception E) {
            E.printStackTrace();
            return "Request failed: " + E.getMessage();
        }
        return "Remove Critical Server request completed.";
    }

    public void setNote(String queryID, String note) {
        try {

            Statement s1 = createResultStatement();

            if (note == null)
                note = "";
            if (note.length() > 0) {
                try {
                    NetFSEUtil.convertFromHex(note);
                } catch (Exception e) {
                    note = NetFSEUtil.convertToHex(note);
                }
            }

            String sql = "update Queries set Note='" + note + "' where Query_ID='" + queryID + "'";
            s1.execute(sql);

            s1.close();
            // c.close();
        } catch (Exception E) {
            E.printStackTrace();
        }
    }

    public String setPasswordAdmin(String user, String password) {
        try {

            String userName = getUserName();
            boolean admin = isAdmin(userName);
            if (!admin)
                return "You must be an admin to execute this function.";

            Statement statement = createMetadataStatement();

            String sql = "update Users set Password='" + password + "' where User_Name='" + user + "'";
            statement.execute(sql);
            statement.close();
            return "Password update complete.";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "Password update failed";
    }

    public String setPasswordUser(String oldPassword, String newPassword) {
        try {

            if (NetFSEClient.IS_TEST_DRIVE)
                return "Password change disabled.";

            String userName = getUserName();

            Statement statement = createMetadataStatement();

            String sql = "select * from Users where User_Name='" + userName + "'";
            ResultSet rs = statement.executeQuery(sql);
            if (rs.next()) {
                String password = rs.getString("Password");
                if (!password.equals(oldPassword)) {
                    rs.close();
                    statement.close();
                    return "The password specified does not match the current password.";
                }
            } else {
                rs.close();
                statement.close();
                return "The specified user does not exist";
            }
            rs.close();

            sql = "update Users set Password='" + newPassword + "' where User_Name='" + userName + "'";
            statement.execute(sql);
            statement.close();
            return "Password updated.";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "Password update failed";
    }

    public String updateCriticalServer(String ip, CriticalServerEntry server) {
        try {

            String userName = getUserName();

            boolean admin = isAdmin(userName);
            if (!admin)
                return "You must be an admin to execute this function.";

            Statement statement = createMetadataStatement();

            String sql = "select * from Critical_Servers where Server_IP='" + ip + "'";
            ResultSet rs = statement.executeQuery(sql);
            if (!rs.next()) {
                rs.close();
                statement.close();
                return "Request failed: no such entry in critical server list ('" + ip + "')";
            }
            rs.close();

            int asSrc = 0;
            if (server.asSrc)
                asSrc = 1;
            int asDst = 0;
            if (server.asDst)
                asDst = 1;

            sql = "update Critical_Servers set Server_IP='" + server.ip + "', As_Src=" + asSrc + ", As_Dst=" + asDst
                    + ", Note='" + NetFSEUtil.convertToHex(server.note) + "' where Server_IP='" + ip + "'";
            // System.out.println(sql);
            statement.execute(sql);

            statement.close();
        } catch (Exception E) {
            E.printStackTrace();
            return "Request failed: " + E.getMessage();
        }
        return "Update Critical Server request completed.";
    }

    public String updateEmailReportConfigs(EmailReportConfigs configs) {
        try {

            String userName = getUserName();

            boolean admin = isAdmin(userName);
            if (!admin)
                return "You must be an admin to execute this function.";

            Statement statement = createMetadataStatement();

            int last = 0;
            String sql = "select * from Email_Report_Config";
            ResultSet rs = statement.executeQuery(sql);
            if (rs.next()) {
                last = rs.getInt("Last");
            }

            sql = "delete from Email_Report_Config";
            statement.execute(sql);

            sql = "insert into Email_Report_Config values ('" + configs.address + "'," + configs.frequency + ",'"
                    + configs.server + "'," + last + "," + configs.port + ")";
            statement.execute(sql);
            statement.close();
        } catch (Exception E) {
            E.printStackTrace();
            return "Request failed: " + E.getMessage();
        }
        return "Email reports configuration change completed.";
    }

    public String updateUser(String userName, UserInfo userInfo) {
        try {

            String user = getUserName();

            boolean admin = isAdmin(user);
            if (!admin)
                return "You must be an admin to execute this function.";

            Statement statement = createMetadataStatement();

            // Check that if the user name is changing that it is unique
            if (!userInfo.userName.equals(userName)) {
                String sql = "select * from Users where User_Name='" + userInfo.userName + "'";
                ResultSet rs = statement.executeQuery(sql);
                if (rs.next()) {
                    // A user exists with this user name, return an error
                    rs.close();
                    statement.close();
                    return "Cannot change the user name from '" + userName + "' to '" + userInfo.userName
                            + "' because a user with that name already exists.";
                } else {
                    // It is OK to change to this user name
                    rs.close();
                }
            }

            int adminVal = 0;
            if (userInfo.admin)
                adminVal = 1;
            String sql = "update Users set User_Name='" + userInfo.userName + "', Real_Name='" + userInfo.realName
                    + "', Admin=" + adminVal + " where User_Name='" + userName + "'";
            statement.execute(sql);
            if (userInfo.password.length() > 0) {
                sql = "update Users set Password='" + userInfo.password + "' where User_Name='" + userName + "'";
                statement.execute(sql);
            }

            statement.close();

            if (!userInfo.userName.equals(userName)) {
                // If the username has changed, update the results database
                statement = createResultStatement();

                sql = "update Queries set User_ID='" + userInfo.userName + "' where User_ID='" + userName + "'";
                statement.execute(sql);
                sql = "update Query_Options set User_ID='" + userInfo.userName + "' where User_ID='" + userName + "'";
                statement.execute(sql);
                statement.close();
            }

            return "Updated user '" + userInfo.userName + "'.";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "Update user failed.";
    }
}
